
package com.kaciula.letsdoit.ui;

import com.kaciula.letsdoit.R;
import com.kaciula.letsdoit.db.WastesDbAdapter;
import com.kaciula.utils.StorageHelper;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;

public class WasteEditActivity extends Activity implements OnClickListener, LocationListener {

    private WastesDbAdapter mDbHelper;

    private LocationManager mLocationManager;

    private PreferenceHelper mPrefHelper;

    private boolean mWantsLocation;

    private boolean mNewLocation;

    private Long mRowId;

    /* Constants */
    private static final String TAG = "WasteEditActivity";

    private static final long MIN_TIME = 60000;

    private static final float MIN_DISTANCE = 10;

    private static final int LOCATION_FORMAT = Location.FORMAT_DEGREES;

    private static final String WANTS_LOCATION = "WANTS_LOCATION";

    /* IDs */
    private static final int DIALOG_NO_GPS_ID = 0;

    private static final int DIALOG_VALIDATION_ID = 1;

    private static final int DIALOG_CONTENT_ID = 2;

    private static final int DIALOG_NO_EXTERNAL_STORAGE_ID = 3;

    private static final int DIALOG_VALIDATION_PERCENT_ID = 4;

    /* Request codes */
    private static final int REQ_CODE_ENABLE_GPS = 0;

    private static final int REQ_CODE_TAKE_PIC1 = 1;

    private static final int REQ_CODE_TAKE_PIC2 = 2;

    /* Views */
    private Dialog mContentDialog;

    private ImageView mPicView1;

    private ImageView mPicView2;

    private TextView mLatView;

    private TextView mLongView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.waste_edit);

        mDbHelper = new WastesDbAdapter(this);
        mDbHelper.open();

        mPrefHelper = ((MyApplication) getApplicationContext()).getPrefHelper();

        Button locationButton = (Button) findViewById(R.id.get_coordinates);
        locationButton.setOnClickListener(this);

        Button contentButton = (Button) findViewById(R.id.content);
        contentButton.setOnClickListener(this);

        Button saveButton = (Button) findViewById(R.id.save);
        saveButton.setOnClickListener(this);

        mPicView1 = (ImageView) findViewById(R.id.pic1);
        mPicView1.setOnClickListener(this);

        mPicView2 = (ImageView) findViewById(R.id.pic2);
        mPicView2.setOnClickListener(this);

        mLatView = (TextView) findViewById(R.id.latitude);
        mLongView = (TextView) findViewById(R.id.longitude);

        Bundle extras = getIntent().getExtras();
        mNewLocation = (extras == null);

        mWantsLocation = false;
        if (mNewLocation) {
            mRowId = mDbHelper.fetchFutureId();
            mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        } else {
            mRowId = extras.getLong(WastesDbAdapter.KEY_ROWID);
            locationButton.setEnabled(false);
        }

        populateFields();
    }

    @Override
    protected void onDestroy() {
        mDbHelper.close();
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putString(WastesDbAdapter.KEY_LAT, mLatView.getText().toString());
        outState.putString(WastesDbAdapter.KEY_LONG, mLongView.getText().toString());
        outState.putBoolean(WANTS_LOCATION, mWantsLocation);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        String text = savedInstanceState.getString(WastesDbAdapter.KEY_LAT);
        mLatView.setText(text);

        text = savedInstanceState.getString(WastesDbAdapter.KEY_LONG);
        mLongView.setText(text);

        mWantsLocation = savedInstanceState.getBoolean(WANTS_LOCATION);

        super.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mWantsLocation) {
            startListening();
        }
    }

    @Override
    protected void onPause() {
        stopListening();
        super.onPause();
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        Dialog dialog;
        AlertDialog.Builder builder;
        String message;

        switch (id) {
            case DIALOG_NO_GPS_ID:
                builder = new AlertDialog.Builder(this);
                builder.setMessage(R.string.gps_disabled).setCancelable(false).setPositiveButton(
                        R.string.yes, new DialogInterface.OnClickListener() {
                            public void onClick(final DialogInterface dialog, final int id) {
                                launchGpsOptions();
                                mWantsLocation = true;
                            }
                        }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {
                        mWantsLocation = false;
                        dialog.dismiss();
                    }
                });
                dialog = builder.create();
                break;
            case DIALOG_VALIDATION_ID:
                builder = new AlertDialog.Builder(this);
                message = "";
                builder.setMessage(message).setCancelable(false).setPositiveButton(R.string.ok,
                        new DialogInterface.OnClickListener() {
                            public void onClick(final DialogInterface dialog, final int id) {
                                dialog.dismiss();
                            }
                        });
                dialog = builder.create();
                break;
            case DIALOG_CONTENT_ID:
                dialog = new Dialog(this);
                dialog.setContentView(R.layout.content_dialog);
                dialog.setTitle(getString(R.string.garbage_content));
                ((Button) dialog.findViewById(R.id.content_ok)).setOnClickListener(this);
                mContentDialog = dialog;
                populateContentDialog(dialog);
                break;
            case DIALOG_NO_EXTERNAL_STORAGE_ID:
                builder = new AlertDialog.Builder(this);
                message = getString(R.string.no_external_storage);
                builder.setMessage(message).setCancelable(false).setPositiveButton(R.string.ok,
                        new DialogInterface.OnClickListener() {
                            public void onClick(final DialogInterface dialog, final int id) {
                                dialog.dismiss();
                            }
                        });
                dialog = builder.create();
                break;
            case DIALOG_VALIDATION_PERCENT_ID:
                builder = new AlertDialog.Builder(this);
                message = getString(R.string.not_100_percent);
                builder.setMessage(message).setCancelable(false).setPositiveButton(R.string.ok,
                        new DialogInterface.OnClickListener() {
                            public void onClick(final DialogInterface dialog, final int id) {
                                dialog.dismiss();
                            }
                        });
                dialog = builder.create();
                break;
            default:
                dialog = null;
                break;
        }

        return dialog;
    }

    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        super.onPrepareDialog(id, dialog);

        switch (id) {
            case DIALOG_VALIDATION_ID:
                String message;
                if ("".equals(mLatView.getText().toString()))
                    message = getString(R.string.no_coordinates);
                else
                    message = getString(R.string.fill_in_all_fields);

                ((AlertDialog) dialog).setMessage(message);
                break;
            default:
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);

        if (resultCode != Activity.RESULT_OK)
            return;

        switch (requestCode) {
            case REQ_CODE_TAKE_PIC1:
                updatePic(1);
                break;
            case REQ_CODE_TAKE_PIC2:
                updatePic(2);
                break;
            default:
                break;
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.save:
                if (saveState()) {
                    setResult(RESULT_OK);
                    finish();
                }
                break;
            case R.id.get_coordinates:
                startListening();
                break;
            case R.id.content:
                showDialog(DIALOG_CONTENT_ID);
                break;
            case R.id.content_ok:
                dismissDialog(DIALOG_CONTENT_ID);
                break;
            case R.id.pic1:
                if (StorageHelper.isAvailableAndWritable()) {
                    startCameraActivity(1);
                } else {
                    showDialog(DIALOG_NO_EXTERNAL_STORAGE_ID);
                }
                break;
            case R.id.pic2:
                if (StorageHelper.isAvailableAndWritable()) {
                    startCameraActivity(2);
                } else {
                    showDialog(DIALOG_NO_EXTERNAL_STORAGE_ID);
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        String text = Location.convert(location.getLatitude(), LOCATION_FORMAT);
        text = text.replace(',', '.');
        mLatView.setText(text);

        text = Location.convert(location.getLongitude(), LOCATION_FORMAT);
        text = text.replace(',', '.');
        mLongView.setText(text);

        Toast.makeText(this, R.string.coordinates_found, Toast.LENGTH_SHORT).show();

        mWantsLocation = false;
        stopListening();
    }

    @Override
    public void onProviderDisabled(String provider) {
        Log.d(TAG, "Provider disabled");
    }

    @Override
    public void onProviderEnabled(String provider) {
        Log.d(TAG, "Provider enabled");
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        Log.d(TAG, "Status changed");
    }

    private boolean saveState() {
        ContentValues args = new ContentValues();

        try {
            double doubVal = Double.valueOf(mLatView.getText().toString());
            args.put(WastesDbAdapter.KEY_LAT, doubVal);

            doubVal = Double.valueOf(mLongView.getText().toString());
            args.put(WastesDbAdapter.KEY_LONG, doubVal);

            EditText lenView = (EditText) findViewById(R.id.length);
            int val = Integer.valueOf(lenView.getText().toString());
            args.put(WastesDbAdapter.KEY_LENGTH, val);

            EditText breadthView = (EditText) findViewById(R.id.breadth);
            val = Integer.valueOf(breadthView.getText().toString());
            args.put(WastesDbAdapter.KEY_BREADTH, val);

            EditText heightView = (EditText) findViewById(R.id.height);
            val = Integer.valueOf(heightView.getText().toString());
            args.put(WastesDbAdapter.KEY_HEIGHT, val);

            CheckBox dispersedView = (CheckBox) findViewById(R.id.dispersed);
            val = dispersedView.isChecked() ? 1 : 0;
            args.put(WastesDbAdapter.KEY_DISPERSED, val);

            EditText equiView = (EditText) findViewById(R.id.equivalent);
            val = Integer.valueOf(equiView.getText().toString());
            args.put(WastesDbAdapter.KEY_EQUIVALENT, val);

            EditText descrView = (EditText) findViewById(R.id.description);
            String text = descrView.getText().toString();
            args.put(WastesDbAdapter.KEY_DESCRIPTION, text);
        } catch (NumberFormatException e) {
            showDialog(DIALOG_VALIDATION_ID);
            return false;
        }

        if (mContentDialog != null) {
            int sum = 0;
            try {
                EditText notRecView = (EditText) mContentDialog.findViewById(R.id.not_recyclable);
                int val = Integer.valueOf(notRecView.getText().toString());
                args.put(WastesDbAdapter.KEY_COMPOSITION_NOT_RECYCLABLE, val);
                sum += val;

                EditText glassView = (EditText) mContentDialog.findViewById(R.id.glass);
                val = Integer.valueOf(glassView.getText().toString());
                args.put(WastesDbAdapter.KEY_COMPOSITION_GLASS, val);
                sum += val;

                EditText metalView = (EditText) mContentDialog.findViewById(R.id.metal);
                val = Integer.valueOf(metalView.getText().toString());
                args.put(WastesDbAdapter.KEY_COMPOSITION_METAL, val);
                sum += val;

                EditText plasticView = (EditText) mContentDialog.findViewById(R.id.plastic);
                val = Integer.valueOf(plasticView.getText().toString());
                args.put(WastesDbAdapter.KEY_COMPOSITION_PLASTIC, val);
                sum += val;

                EditText paperView = (EditText) mContentDialog.findViewById(R.id.paper);
                val = Integer.valueOf(paperView.getText().toString());
                args.put(WastesDbAdapter.KEY_COMPOSITION_PAPER, val);
                sum += val;

                EditText tireView = (EditText) mContentDialog.findViewById(R.id.tire);
                val = Integer.valueOf(tireView.getText().toString());
                args.put(WastesDbAdapter.KEY_COMPOSITION_TIRE, val);
                sum += val;

                EditText bigVolView = (EditText) mContentDialog.findViewById(R.id.big_volume);
                val = Integer.valueOf(bigVolView.getText().toString());
                args.put(WastesDbAdapter.KEY_COMPOSITION_BIG_VOLUME, val);
                sum += val;

                EditText consView = (EditText) mContentDialog
                        .findViewById(R.id.construction_material);
                val = Integer.valueOf(consView.getText().toString());
                args.put(WastesDbAdapter.KEY_COMPOSITION_CONSTRUCTION_MATERIAL, val);
                sum += val;

                /* total percent must be 100 */
                if (sum != 100) {
                    showDialog(DIALOG_VALIDATION_PERCENT_ID);
                    return false;
                }
            } catch (NumberFormatException e) {
                showDialog(DIALOG_VALIDATION_ID);
                return false;
            }
        } else {
            if (mNewLocation) {
                showDialog(DIALOG_VALIDATION_ID);
                return false;
            }
        }

        if (mNewLocation) {
            mDbHelper.createWaste(args);
        } else {
            mDbHelper.updateWaste(mRowId, args);
        }

        return true;
    }

    private void populateFields() {
        TextView nameView = (TextView) findViewById(R.id.waste);

        nameView.setText(getString(R.string.waste) + " " + mRowId);
        updatePic(1);
        updatePic(2);

        if (!mNewLocation) {
            EditText lenView = (EditText) findViewById(R.id.length);
            EditText breadthView = (EditText) findViewById(R.id.breadth);
            EditText heightView = (EditText) findViewById(R.id.height);
            CheckBox dispersedView = (CheckBox) findViewById(R.id.dispersed);
            EditText equiView = (EditText) findViewById(R.id.equivalent);
            EditText descrView = (EditText) findViewById(R.id.description);

            Cursor waste = mDbHelper.fetchWaste(mRowId);
            startManagingCursor(waste);

            String text;
            text = Location.convert(waste.getDouble(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_LAT)), LOCATION_FORMAT);
            text = text.replace(',', '.');
            mLatView.setText(text);

            text = Location.convert(waste.getDouble(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_LONG)), LOCATION_FORMAT);
            text = text.replace(',', '.');
            mLongView.setText(text);

            text = waste.getString(waste.getColumnIndexOrThrow(WastesDbAdapter.KEY_LENGTH));
            lenView.setText(text);

            text = waste.getString(waste.getColumnIndexOrThrow(WastesDbAdapter.KEY_BREADTH));
            breadthView.setText(text);

            text = waste.getString(waste.getColumnIndexOrThrow(WastesDbAdapter.KEY_HEIGHT));
            heightView.setText(text);

            int dispersed = waste
                    .getInt(waste.getColumnIndexOrThrow(WastesDbAdapter.KEY_DISPERSED));
            dispersedView.setChecked(dispersed != 0 ? true : false);

            text = waste.getString(waste.getColumnIndexOrThrow(WastesDbAdapter.KEY_EQUIVALENT));
            equiView.setText(text);

            text = waste.getString(waste.getColumnIndexOrThrow(WastesDbAdapter.KEY_DESCRIPTION));
            descrView.setText(text);
        }
    }

    private void populateContentDialog(Dialog dialog) {
        if (!mNewLocation) {
            EditText notRecView = (EditText) dialog.findViewById(R.id.not_recyclable);
            EditText glassView = (EditText) dialog.findViewById(R.id.glass);
            EditText metalView = (EditText) dialog.findViewById(R.id.metal);
            EditText plasticView = (EditText) dialog.findViewById(R.id.plastic);
            EditText paperView = (EditText) dialog.findViewById(R.id.paper);
            EditText tireView = (EditText) dialog.findViewById(R.id.tire);
            EditText bigVolView = (EditText) dialog.findViewById(R.id.big_volume);
            EditText consView = (EditText) dialog.findViewById(R.id.construction_material);

            Cursor waste = mDbHelper.fetchWaste(mRowId);
            startManagingCursor(waste);

            String text = waste.getString(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_NOT_RECYCLABLE));
            notRecView.setText(text);

            text = waste.getString(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_GLASS));
            glassView.setText(text);

            text = waste.getString(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_METAL));
            metalView.setText(text);

            text = waste.getString(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_PLASTIC));
            plasticView.setText(text);

            text = waste.getString(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_PAPER));
            paperView.setText(text);

            text = waste.getString(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_TIRE));
            tireView.setText(text);

            text = waste.getString(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_BIG_VOLUME));
            bigVolView.setText(text);

            text = waste.getString(waste
                    .getColumnIndexOrThrow(WastesDbAdapter.KEY_COMPOSITION_CONSTRUCTION_MATERIAL));
            consView.setText(text);
        }
    }

    /**
     * helpers for starting/stopping monitoring of GPS changes below
     */
    private void startListening() {
        if (mLocationManager != null) {
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME,
                    MIN_DISTANCE, this);
            if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                showDialog(DIALOG_NO_GPS_ID);
            } else {
                mWantsLocation = true;
                setProgressBarIndeterminateVisibility(true);
            }
        }
    }

    private void stopListening() {
        if (mLocationManager != null) {
            mLocationManager.removeUpdates(this);
            setProgressBarIndeterminateVisibility(false);
        }
    }

    private void launchGpsOptions() {
        final ComponentName toLaunch = new ComponentName("com.android.settings",
                "com.android.settings.SecuritySettings");
        final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setComponent(toLaunch);
        startActivityForResult(intent, REQ_CODE_ENABLE_GPS);
    }

    private void startCameraActivity(int no) {
        String path = mPrefHelper.getPicPath(mRowId, no);
        File file = StorageHelper.getFile(path);
        Uri outUri = Uri.fromFile(file);

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outUri);

        startActivityForResult(intent, no == 1 ? REQ_CODE_TAKE_PIC1 : REQ_CODE_TAKE_PIC2);
    }

    private void updatePic(int no) {
        String path = mPrefHelper.getPicPath(mRowId, no);

        Bitmap bitmap = StorageHelper.getBitmap(path, Constants.SAMPLE_SIZE);
        if (bitmap != null) {
            switch (no) {
                case 1:
                    mPicView1.setImageBitmap(bitmap);
                    break;
                case 2:
                    mPicView2.setImageBitmap(bitmap);
                    break;
                default:
                    break;
            }
        }
    }
}
